#include <iostream>
#include "spline.h"
#include "cardinal_spline.h"
#include<cstdlib>
#include <ctime>
#include "Eigen/Dense"
//#include "polynomial.h"
using namespace std;

Point X;
Point C1;
Point C2;
vector<double> xx;
void getpoint(Function &g,int N,double lhs,double rhs){
    for (int i=0;i<N;i++){
        X.x.push_back(lhs+(rhs-lhs)*i/(N-1));
        X.f.push_back(g(X.x[i]));
    }
  // X.showpoint(X);
}
vector<double> midpoint(Point X){
    vector<double> mp;
    for(int i=0;i<X.x.size();i++){
        mp.push_back((X.x[i]+X.x[i+1])/2);
    }
    return mp;
}
vector<double> getsample_uniform(int N,double lhs,double rhs){
    for(int i=0;i<N;i++){
        xx.push_back(lhs+(rhs-lhs)*i/(N-1));
    }
    return xx;
}

class Func1 : public Function{
public:
    double operator () (const double &x) const{
        return 1.0/(1+25*x*x);
    }
} func1;

class Func2 : public Function{
public:
    double operator () (const double &x) const{
        return 1.0/(1+x*x);
    }
} func2;
void getpointC1(Function &func){
    for (int i=1;i<=11;i++){
        C1.x.push_back(-6+i);
        C1.f.push_back(func(C1.x[i-1]));
    }
}
void getpointC2(Function &func){
    for (int i=0;i<10;i++){
        C2.x.push_back(i-4.5);
        C2.f.push_back(func(C2.x[i]));
    }
}

void testA(int N,string z){
    getpoint(func1, N, -1, 1);
    getsample_uniform(4000, -1, 1);
    for(int i=0;i<4000;i++){
        PiecewisePoly(func1, X).condition(z,xx[i]);//拟合函数
    }
}
void maxerror(int N,string z){
    getpoint(func1, N, -1, 1);
    getsample_uniform(5000, -1, 1);
    for(int i=0;i<N;i++){
        PiecewisePoly(func1,X).condition(z, midpoint(X)[i]);
    }
}
void testC(string z){
    getpointC1(func2);
    getpointC2(func2);
    getsample_uniform(4000, -5, 5);
    for(int i=0;i<5000;i++){
        if(z=="cubic"){
            cardinal_spline(func2,C1).condition("complete_cardinal_cubic",C1,11,xx[i]);
            
        }
        if(z=="quadratic"){
            cardinal_spline(func2,C2).condition("complete_cardinal_quadratic",C2,10,xx[i]);
        }
    }
}

int main() {
    //testA(6,"complete");
    //testA(11,"complete");
    //testA(21,"complete");
    //testA(41,"complete");
    //testA(81,"complete");
    //testA(6,"natural");
    //testA(11,"natural");
    //testA(21,"natural");
    //testA(41,"natural");
    //testA(81,"natural");
    //testA(6, "notaknot");
    //testA(11, "notaknot");
    //testA(21, "notaknot");
    //testA(41, "notaknot");
    //testA(81, "notaknot");
    //testC("cubic");
    testC("quadratic");
}
